package com.wxw.jwt.shiro;


import com.wxw.jwt.config.JwtFilter;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
import org.apache.shiro.mgt.DefaultSubjectDAO;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.context.annotation.Lazy;

import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;

/**
 * @author wxw
 * @data 2021/8/30 00 :28
 * @description
 */


@Configuration
public class ShiroConfig {

    @Bean("jwtFilter")
    public JwtFilter jwtFilter() {
        return new JwtFilter();
    }


        /**
         * 自定义realm
         */
        @Bean("myRealm")
        public MyRealm myRealm() {
            MyRealm myRealm = new MyRealm();
//        myRealm.setCredentialsMatcher(credentialMatcher);
            return myRealm;
        }

        @Bean("securityManager")
        public DefaultWebSecurityManager securityManager(@Qualifier("myRealm") MyRealm myRealm) {
            DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
            manager.setRealm(myRealm);
            /*
             * 关闭shiro自带的session，详情见文档
             */
            DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();
            DefaultSessionStorageEvaluator defaultSessionStorageEvaluator = new DefaultSessionStorageEvaluator();
            defaultSessionStorageEvaluator.setSessionStorageEnabled(false);
            subjectDAO.setSessionStorageEvaluator(defaultSessionStorageEvaluator);
            manager.setSubjectDAO(subjectDAO);
            return manager;
        }

//        @Bean("shiroFilter")
//        public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("securityManager")DefaultWebSecurityManager securityManager) {
//            ShiroFilterFactoryBean filter = new ShiroFilterFactoryBean();
//            filter.setSecurityManager(securityManager);
//            LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
//            // 路径匹配的顺序就是put进去的顺序（最先匹配原则）
//            // login接口不需要认证
//            filterChainDefinitionMap.put("/auth/login", "anon");
//            // getInfo需要认证
//            filterChainDefinitionMap.put("/auth/getInfo", "authc");
//            filterChainDefinitionMap.put("/**", "authc");
//
//            filter.setLoginUrl("/auth/login");
//            filter.setSuccessUrl("/auth/getInfo");
//            filter.setUnauthorizedUrl("/auth/error");
//            filter.setFilterChainDefinitionMap(filterChainDefinitionMap);
//            return filter;
//
//        }

            @Bean("shiroFilter")
        public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("securityManager")DefaultWebSecurityManager securityManager) {
                ShiroFilterFactoryBean filter = new ShiroFilterFactoryBean();
                filter.setSecurityManager(securityManager);

                Map<String, Filter> filterMap = new LinkedHashMap<>();
                filterMap.put("jwt", new JwtFilter());
                filter.setFilters(filterMap);

                LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap()
                {{
                    // login接口不需要认证
                    put("/auth/login", "anon");
                    put("/auth/loginJwt", "anon");
                    put("/**/**.*", "anon");
                    put("/v2/api-docs", "anon");
                    put("/swagger-resources/**", "anon");
                    //默认
                    put("/swagger-ui.html", "anon");

                    //bootstarp-ui
                    put("/doc.html", "anon");
                    //mg-ui
                    put("/document.html", "anon");
                    put("/thinkswagger/index.html", "anon");
                    put("/", "anon");
                    put("/**", "jwt");
                }};

                filter.setFilterChainDefinitionMap(filterChainDefinitionMap);
                return filter;

        }
        /**注册shiro的Filter 拦截请求*/
        @Bean
        public FilterRegistrationBean<Filter> filterRegistrationBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager) throws Exception {
            FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean<>();
            filterRegistrationBean.setFilter((Filter) Objects.requireNonNull(this.shiroFilterFactoryBean(securityManager).getObject()));
            filterRegistrationBean.addInitParameter("targetFilterLifecycle","true");
            //bean注入开启异步方式
            filterRegistrationBean.setAsyncSupported(true);
            filterRegistrationBean.setEnabled(true);
            filterRegistrationBean.setDispatcherTypes(DispatcherType.REQUEST);
            return filterRegistrationBean;
        }


        /**
         * shiro声明周期
         * @return
         */
        @Bean
        public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
            return new LifecycleBeanPostProcessor();
        }

        // 以下配置开启shiro注解(@RequiresPermissions)

        @Bean
        @DependsOn({"lifecycleBeanPostProcessor"})
        public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() {
            DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
            // 强制使用cglib，防止重复代理和可能引起代理出错的问题
            // https://zhuanlan.zhihu.com/p/29161098
            advisorAutoProxyCreator.setProxyTargetClass(true);
            return advisorAutoProxyCreator;
        }

        /**
         * 启用shiro注解
         */
        @Bean
        public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(@Qualifier("securityManager") DefaultWebSecurityManager securityManager) {
            AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
            authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
            return authorizationAttributeSourceAdvisor;
        }
    }



